/**
 *  @file SQLiteCursor.h
 */
#ifndef _SQLITECURSOR_H_
#define _SQLITECURSOR_H_

#include "../../common/BaseObject.h"
#include "../../lang/TypeInfo.h"
#include "../../collections/HashtableT.h"
#include "../../lang/Primitive.h"

namespace cppflib
{

namespace collections 
{
   class BinBuf;
}

namespace util
{
   class DateTime;
}

namespace database
{

namespace sqlite
{

class SQLiteCommand;
class SQLiteBlobIO;
class SQLiteDatabase;

/**
 *  Class to read data after a SQL query
 */
class _DLLAPI SQLiteCursor : public BaseObject
{
private:
    ptrany_t pStmt;
    ptrany_t pDB;
    collections::HashtableT<CFString, lang::Int32> *pColName2IndexCache;

private:
    SQLiteCursor(void);
    SQLiteCursor(ptrany_t pStmt, SQLiteDatabase * pDB);
    void GetColumnType(int index, lang::TypeInfo& typeInfo) const;
    int GetColumnIndexFromName(const CFString &colName, bool isThrowExpIfNotFound);
    PRIVATE bool EvaluateSqlStmt(ptrany_t pStmt, bool isNonQuery);

public:    
    virtual ~SQLiteCursor(void);

    bool Read();
    void Close();

    int GetColumnCount() const;
    const lang::TypeInfo * GetColumnType(int index) const;
    const CFString * GetColumnName(int index) const;
    void GetColumnName(int index, CFString &colName) const;
    const CFString * GetTableName(int index) const;
    void GetTableName(int index, CFString &tabName) const;
    const CFString * GetDatabaseName(int index) const;
    void GetDatabaseName(int index, CFString &dbName) const;

    /* Get column value by index */
    bool IsNull(int index);    
    int GetByteCount(int index);
    int GetBlob(int index, int blobOffset, sz_t fetchLength, collections::BinBuf & binBuf);
    int GetBlob(int index, collections::BinBuf & binBuf);
    SQLiteBlobIO * GetBlobIO(int index);
    int GetUTF16CharCount(int index);
    int GetString(int index, int strOffset, sz_t fetchLength, CFString &s);
    int GetString(int index, CFString &s);
    bool GetDateTime(int index, util::DateTime &val);
    bool GetDouble(int index, double &val);
    bool GetInt32(int index, int &val);
    bool GetInt64(int index, i64_t &val);

    /* Get column value by column name */
    bool IsNull(const CFString &colName);
    int GetByteCount(const CFString &colName);
    int GetBlob(const CFString &colName, int blobOffset, sz_t fetchLength, collections::BinBuf & binBuf);
    int GetBlob(const CFString &colName, collections::BinBuf & binBuf);
    SQLiteBlobIO * GetBlobIO(const CFString &blobColName, int index = 0);
    int GetUTF16CharCount(const CFString &colName);
    int GetString(const CFString &colName, int strOffset, sz_t fetchLength, CFString &s);
    int GetString(const CFString &colName, CFString &s);
    bool GetDateTime(const CFString &colName, util::DateTime &val);
    bool GetDouble(const CFString &colName, double &val);
    bool GetInt32(const CFString &colName, int &val);
    bool GetInt64(const CFString &colName, i64_t &val);

    friend class SQLiteCommand;
};

} // end of namespace sqlite

} // end of namespace database

} // end of namespace cppflib


#endif
